package com.cevent.template.prod.generate;

import com.cevent.template.prod.util.ConnectionSet;
import com.cevent.template.prod.util.DataSet;
import com.cevent.template.prod.util.FieldSet;
import com.cevent.template.prod.util.FreemarkerSet;
import freemarker.template.TemplateException;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author cevent
 * @create 2025/1/26 23:21
 */
public class ServerGenerator {
    public static void main(String[] args) throws IOException, TemplateException {
        //自动生成的文件类型
        String directoryDtoName="dto";
        String directoryDtoChildrenName="childrenDto";
        String directoryDefMapperName="defMapper";
        String directoryDefMapperInterfaceName="defMapperInterface";
        String directoryServiceName="service";
        String directoryControllerName="controller";
        String directoryVueName="vue";

        //指定freemarker生成文件的包名（模块名），目前生成的持久层相关的代码和业务处理都放在common公共模块，其他业务再增加
        String commonModule="common";
        String cmsModule="cms";
        String systemModule="system";
        //直接分配给前端指定模组，这里因为不是一个项目，无法直接分类TODO
        String frontModule="";

        //控台端
        String admin="admin";
        String client="client";
        //客户端

        //模版配置
        String suffixName=".ftl";
        String dtoFtl="dto"+suffixName;
        String dtoChildrenFtl="childrenDto"+suffixName;
        String defMapperFtl=directoryDefMapperName+suffixName;
        String defMapperInterfaceFtl=directoryDefMapperInterfaceName+suffixName;

        String serviceFtl="service"+suffixName;
        String controllerFtl="controller"+suffixName;
        String vueFtl="vue"+suffixName;
        FreemarkerSet.modeName="prod";
        FreemarkerSet.ftlPath=FreemarkerSet.templateName+ "\\src\\main\\java\\com\\cevent\\"+FreemarkerSet.templateName+"\\"+FreemarkerSet.modeName+"\\ftl\\";

        //生成文件配置
        String fileSuffixName=".java";
        /**
         *.java在编译器中，注意写的是什么类型结尾
         * 如果是.vue则直接写入.vue
         */
        String dtoFileName= DataSet.prefixBigWrite(directoryDtoName)+fileSuffixName;
        String dtoChildrenFileName= DataSet.prefixBigWrite(directoryDtoChildrenName)+fileSuffixName;
        String defMapperFileName= DataSet.prefixBigWrite(directoryDefMapperName)+".xml";
        String defMapperInterfaceFileName=DataSet.prefixBigWrite(directoryDefMapperName)+fileSuffixName;

        String serviceFileName=DataSet.prefixBigWrite(directoryServiceName)+fileSuffixName;
        String controllerFileName=DataSet.prefixBigWrite(directoryControllerName)+fileSuffixName;
        String vueFileName=".vue";

        /**
         * 公共参数配置
         */
        FreemarkerSet.CLASS_NAME_BIG="ModuleBase";
        FreemarkerSet.CLASS_NAME_SMALL="moduleBase";
        FreemarkerSet.TABLE_NAME_CN= ConnectionSet.getTableComment("");


        String dtoPath=commonModule+ "\\src\\main\\java\\com\\cevent\\"+commonModule+"\\"+directoryDtoName+"\\";
        String dtoChildrenPath=commonModule+ "\\src\\main\\java\\com\\cevent\\"+commonModule+"\\"+directoryDtoName+"\\";
        String defMapperPath=commonModule+ "\\src\\main\\resources\\mapper\\defMapper\\";
        String defMapperInterfacePath=commonModule+ "\\src\\main\\java\\com\\cevent\\"+commonModule+"\\"+"mapper\\"+directoryDefMapperName+"\\";

        String servicePath=commonModule+ "\\src\\main\\java\\com\\cevent\\"+commonModule+"\\"+directoryServiceName+"\\";
        String cmsAdminContollerPath=cmsModule+ "\\src\\main\\java\\com\\cevent\\"+cmsModule+"\\"+directoryControllerName+"\\"+admin+"\\";
        //vue文件直接分配到template下的test/file
        String vuePath=FreemarkerSet.templateName+ "\\src\\main\\java\\com\\cevent\\"+FreemarkerSet.templateName+"\\"+FreemarkerSet.modeName+"\\file\\";

        //xml的配置的表
        String generatorPath=commonModule+"\\src\\main\\resources\\generator\\generatorConfig.xml";

        //读取xml
        File xmlFile=new File(generatorPath);
        SAXReader domReader=new SAXReader();
        try {
            Document document=domReader.read(xmlFile);
            Element element=document.getRootElement();
            Element context=element.element("context");
            //定义遍历table的element对象,获取table节点
            Element tableElement=context.elementIterator("table").next();
            //获取ClassName
            String ClassName=tableElement.attributeValue("domainObjectName");
            //转className
            String className=ClassName.substring(0,1).toLowerCase()+ClassName.substring(1);
            //原始表明table_name
            String tableName=tableElement.attributeValue("tableName");
            //表注释
            String tableNameCN=ConnectionSet.getTableComment(tableName);
            //获取所有列信息
            List<FieldSet> fieldSetList=ConnectionSet.getColumnInfo(tableName);
            //获取所有列的类型集合
            Set<String> typeSet=DataSet.getJavaTypes(fieldSetList);

            //Map数据,传递到ftl文件的动态变量
            Map<String,Object> map=new HashMap<>();
            map.put("CLASS_NAME_BIG",ClassName);
            map.put("CLASS_NAME_SMALL",className);
            map.put("TABLE_NAME",tableName);
            map.put("TABLE_NAME_CN",tableNameCN);
            //controller包名索引名称：cms内容放入，其他放入公共commonModule
            map.put("CMS_MODULE_NAME",cmsModule);
            map.put("COMMON_MODULE_NAME",commonModule);
            map.put("FIELD_TYPE_LIST",typeSet);
            map.put("FIELD_SET_LIST",fieldSetList);

            //判断是否需要生成childrenDto
            Boolean hasChildren=false;
            hasChildren=fieldSetList.stream().anyMatch(item->item.getNameSmallHump().contains("parentId"));
            // List<FieldSet> hasParents= fieldSetList.stream().filter(item-> item.getNameSmallHump().contains("parentId")).collect(Collectors.toList());

            /****************************************生成文件****************************************/
            //生成dto
            generatorFile(dtoFtl,dtoPath+FreemarkerSet.CLASS_NAME_BIG+dtoFileName,map);
            if(hasChildren){
                //生成childrenDto
                generatorFile(dtoChildrenFtl,dtoChildrenPath+FreemarkerSet.CLASS_NAME_BIG+dtoChildrenFileName,map);
                generatorFile(defMapperInterfaceFtl,defMapperInterfacePath+ClassName+defMapperInterfaceFileName,map);
                generatorFile(defMapperFtl,defMapperPath+ClassName+defMapperFileName,map);
            }

            //生成service
            generatorFile(serviceFtl,servicePath+FreemarkerSet.CLASS_NAME_BIG+serviceFileName,map);
            //生成controller
            generatorFile(controllerFtl,cmsAdminContollerPath+FreemarkerSet.CLASS_NAME_BIG+controllerFileName,map);

        } catch (DocumentException e) {
            throw new RuntimeException(e);
        }




    }

    public static void generatorFile(String ftlName,String targetFileName,Map<String,Object> map) throws IOException, TemplateException {
        //初始化模版配置
        FreemarkerSet.initConfig(ftlName);
        //生成模版文件
        FreemarkerSet.generateFile(targetFileName,map);
    }

}
